package com.yiyuan.app.filter;

import com.guaike.core.entity.constant.HttpHeaderConstant;
import com.guaike.core.redis.helper.LoginHelper;
import com.guaike.core.web.helper.RequestSignHelper;
import com.yiyuan.app.entity.result.AppUser;
import com.yiyuan.app.entity.result.SeriesUseApp;
import com.yiyuan.app.service.BaseUtilService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBucket;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Slf4j
public class CheckUseAppFilter implements Filter {


    private static final String[] WHITE_URLS = new String[]{"/doc.html", "/webjars/bycdao-ui", "/swagger-resources", "/v2/api-docs"};

    private BaseUtilService baseUtilService;

    private RedissonClient redissonClient;

    public void setBaseUtilService(BaseUtilService baseUtilService) {
        this.baseUtilService = baseUtilService;
    }

    public void setRedissonClient(RedissonClient redissonClient) {
        this.redissonClient = redissonClient;
    }

    @SneakyThrows
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        String url = request.getRequestURI();
        String[] var6 = WHITE_URLS;
        int var7 = var6.length;
        String uri;
        for (int var8 = 0; var8 < var7; ++var8) {
            uri = var6[var8];
            if (url.contains(uri)) {
                filterChain.doFilter(servletRequest, servletResponse);
                return;
            }
        }

        if (RequestSignHelper.isNoSign(url)) {
            filterChain.doFilter(servletRequest, servletResponse);
            return;
        }
        if (RequestSignHelper.isNoLogin(url)) {
            filterChain.doFilter(servletRequest, servletResponse);
            return;
        }
        String accessToken = request.getHeader(HttpHeaderConstant.HEADER_NAME_TOKEN);
        AppUser user = LoginHelper.getUserFromCache(this.redissonClient, accessToken);
        if (Objects.isNull(user)) {
            filterChain.doFilter(servletRequest, servletResponse);
            return;
        }
        LocalDate today = LocalDate.now();
        String key = user.getUserId() + today.toString() + "task";
        baseUtilService.setTask(key, user.getUserId());
        String lockKey = "lockKey:" + user.getUserId();
        RLock lock = redissonClient.getLock(lockKey);
        Boolean res = false;
        try {
            // lock.lock(1*30, TimeUnit.SECONDS); //  一直等待这加锁,上锁以后30秒自动解锁
            res = lock.tryLock(10 * 1000, 30 * 1000, TimeUnit.MILLISECONDS);//尝试加锁，最多等待10秒，上锁以后30秒自动解锁
            if (!res) {
                log.warn("testDistrubLock1>>lockKey:{}, 未获取到锁>>>>>>>>>>>>>>>>>>>>>>>>", lockKey);
                filterChain.doFilter(servletRequest, servletResponse);
                return;
            }
            RBucket<SeriesUseApp> bucket = redissonClient.getBucket("app_series:use" + user.getUserId());
            if (Objects.isNull(bucket.get())) {
                SeriesUseApp seriesUseApp = new SeriesUseApp();
                seriesUseApp.setDays(1);
                seriesUseApp.setFinalUseDate(today.format(DateTimeFormatter.ISO_DATE));
                bucket.set(seriesUseApp);
                baseUtilService.dealSeriesLoginTask(user.getUserId(), seriesUseApp.getDays());
            } else {
                SeriesUseApp seriesUseApp = bucket.get();
                long daysBetween = ChronoUnit.DAYS.between(LocalDate.parse(seriesUseApp.getFinalUseDate(), DateTimeFormatter.ISO_DATE), today);
                if (daysBetween > 1) {
                    baseUtilService.dealSeriesLoginTask(user.getUserId(), seriesUseApp.getDays() + 1);
                    seriesUseApp.setFinalUseDate(today.format(DateTimeFormatter.ISO_DATE));
                    seriesUseApp.setDays(seriesUseApp.getDays() + 1);
                    bucket.set(seriesUseApp);
                }
            }
        } catch (InterruptedException e) {
            log.error("CheckUseAppFilter发生异常:{}", e);
        } finally {
            if (res) {
                lock.forceUnlock();
                log.info("testDistrubLock1>>lockKey:{},--已释放锁[{}]--", lockKey, lockKey);
            }
        }
        filterChain.doFilter(servletRequest, servletResponse);
    }

}
